/**
 * WebSocket 通信模块
 * 负责与服务器建立实时连接并处理各种业务消息
 */

import { ElMessage } from 'element-plus'
import { LocalStorage } from '@/utils/storage'
import { useUserStore } from '@/stores/user'
import { handlePrintMessage as processPrintMessage } from './printer'
import { handleCXTMessage as processCXTMessage, orderStateReport as cxtOrderStateReport } from './cxt/operations'
import { wsLogger } from '@/utils/wsLogger'
import { bus } from '@/utils/bus'

// WebSocket 消息类型定义
interface WebSocketMessage {
    s: string // 消息类型
    status?: number // 状态码
    message?: string // 消息内容
    message_id?: string // 消息ID
    data?: any // 数据内容
}

// 登录消息接口
interface LoginMessage extends WebSocketMessage {
    s: 'login'
    store_id: string | null
    token: string
    version: string
    computer_real_name: string
}

// 心跳消息接口
interface HeartbeatMessage extends WebSocketMessage {
    s: 'heartbeat'
}

// ACK确认消息接口
interface AckMessage extends WebSocketMessage {
    s: 'ack'
    message_id: string // 要确认的消息ID
}


/**
 * 获取计算机名称
 * @returns 计算机名称
 */
async function getComputerName(): Promise<string> {
    try {
        if (!(window as any).system) {
            return 'unknown'
        }

        let computerName = await (window as any).system.getComputerName()
        return computerName
    } catch (error) {
        return 'unknown'
    }
}

/**
 * 订单状态报告
 * 在心跳时执行，用于同步订单状态
 */
async function orderStateReport(): Promise<void> {
    try {
        // 执行订单状态报告
        cxtOrderStateReport()
    } catch (error) {
        // 静默处理错误
    }
}

/**
 * 处理打印消息
 * @param messageData 打印消息数据
 */
async function handlePrintMessage(messageData: any): Promise<void> {
    try {
        await processPrintMessage(messageData)
    } catch (error) {
        ElMessage.error('打印任务处理失败')
    }
}

/**
 * 处理厨信通消息
 * @param messageData 厨信通消息数据
 */
async function handleCXTMessage(messageData: any): Promise<void> {
    try {
        console.log('收到厨信通消息:', messageData)
        await processCXTMessage(messageData)
    } catch (error) {
        console.error('处理厨信通消息失败:', error)
        // ElMessage.error('厨信通消息处理失败')
        try {
            // 等待一段时间后再尝试，避免连续快速重试
            await new Promise(resolve => setTimeout(resolve, 1000))
            // 二次处理消息
            await processCXTMessage(messageData)
        } catch (retryError) {
            console.error('二次处理厨信通消息失败:', retryError)
            // ElMessage.error('二次厨信通消息处理失败')

        }
    }
}

/**
 * 处理系统消息通知
 * @param message 消息对象
 */
function handleSystemMessage(message: WebSocketMessage): void {
    if (message.status !== 200) {
        ElMessage.error('消息通知失败')
        return
    }
    // 通知桌台列表组件刷新数据
    bus.emit('desk-list-refresh', message.data)
}
   
   // 处理挂账相关的消息通知
function handleGuazhangMessage(message: any): void {
    debugger
    switch (message?.data?.type) {
        case 5:
            bus.emit('guazhang-list-refresh')
            break
        default:
            break
    }
}
/**
 * 发送ACK确认消息
 * @param messageId 要确认的消息ID
 */
function sendAckMessage(messageId: string): void {
    if (!webSocketManager.isConnected) {
        console.warn('WebSocket未连接，无法发送ACK确认')
        return
    }

    const ackData: AckMessage = {
        s: 'ack',
        message_id: messageId
    }

    try {
        webSocketManager.sendMessage(JSON.stringify(ackData))
    } catch (error) {
        console.error('❌ 发送ACK确认失败:', error)
    }
}

/**
 * WebSocket 连接管理类
 */
export class WebSocketManager {
    private socket: WebSocket | null = null
    private interval: NodeJS.Timeout | null = null
    private reconnectTimeout: NodeJS.Timeout | null = null
    private readonly baseReconnectDelay = 1000 // 基础重连延迟 5 秒
    private readonly maxReconnectDelay = 300000 // 最大重连延迟 5 分钟
    private reconnectAttempts = 0 // 重连尝试次数
    private readonly heartbeatInterval = 5000 // 心跳间隔 5 秒
    private readonly heartbeatTimeout = 5000 // 心跳超时 5 秒
    private processedMessages: Set<string> = new Set() // 消息去重
    private isManualDisconnect = false // 是否手动断开连接
    private hasLoggedIn = false // 是否已登录
    private lastHeartbeatTime = 0 // 最后一次心跳时间
    private heartbeatTimeoutTimer: NodeJS.Timeout | null = null // 心跳超时定时器
    private heartbeatSendCount = 0 // 心跳发送次数
    private isHeartbeatRunning = false // 心跳是否正在运行
    private isOnline = navigator.onLine // 网络状态

    /**
     * 启动网络检测
     */
    private startNetworkCheck(): void {
        wsLogger.info('NETWORK', '启动网络状态检测')

        // 监听浏览器网络状态变化
        window.addEventListener('online', () => {
            this.isOnline = true
            wsLogger.info('NETWORK', '网络状态: 在线', null, { networkStatus: true })
            this.handleNetworkChange()
        })

        window.addEventListener('offline', () => {
            this.isOnline = false
            wsLogger.warn('NETWORK', '网络状态: 离线', null, { networkStatus: false })
            this.handleNetworkChange()
        })
    }

    /**
     * 停止网络检测
     */
    private stopNetworkCheck(): void {
        wsLogger.info('NETWORK', '停止网络状态检测')
        // 移除事件监听器
        window.removeEventListener('online', this.handleNetworkChange.bind(this))
        window.removeEventListener('offline', this.handleNetworkChange.bind(this))
    }

    /**
     * 处理网络状态变化
     */
    private handleNetworkChange(): void {
        if (this.isOnline) {
            // 网络恢复时，如果WebSocket未连接则重连
            if (!this.isConnected && !this.isManualDisconnect) {
                this.connect()
            }
        } else {
            // 网络断开时，主动断开WebSocket连接
            if (this.socket) {
                console.log('断开了');

                this.socket.close()
            }
        }
    }

    /**
     * 创建 WebSocket 连接
     */
    connect(): void {
        // 检查是否已经存在有效连接
        if (this.socket && this.socket.readyState === WebSocket.OPEN) {
            wsLogger.debug('CONNECTION', 'WebSocket已连接，跳过重复连接', null, { readyState: this.socket.readyState })
            return
        }

        // 如果正在连接中，也跳过
        if (this.socket && this.socket.readyState === WebSocket.CONNECTING) {
            wsLogger.debug('CONNECTION', 'WebSocket正在连接中，跳过重复连接', null, { readyState: this.socket.readyState })
            return
        }
        // 重置手动断开标志
        this.isManualDisconnect = false

        // 检查WebSocket支持
        if (!('WebSocket' in window)) {
            wsLogger.error('CONNECTION', '当前浏览器不支持WebSocket连接')
            ElMessage.error('当前浏览器不支持WebSocket连接')
            return
        }

        // 检查WebSocket URL是否配置
        const socketUrl = import.meta.env.VITE_BASE_SOCKET
        if (!socketUrl) {
            wsLogger.error('CONNECTION', 'WebSocket连接地址未配置')
            ElMessage.error('WebSocket连接地址未配置')
            return
        }

        // 创建 WebSocket 连接
        try {
            wsLogger.info('CONNECTION', `尝试连接WebSocket (第${this.reconnectAttempts + 1}次)`, null, { url: socketUrl, attempt: this.reconnectAttempts + 1 })
            this.socket = new WebSocket(socketUrl)
            this.setupEventListeners()
        } catch (error) {
            wsLogger.error('CONNECTION', 'WebSocket连接创建失败', error)
            ElMessage.error('WebSocket连接创建失败: ' + (error as Error).message)
        }
    }

    /**
     * 设置事件监听器
     */
    private setupEventListeners(): void {
        if (!this.socket) return

        // 连接成功事件
        this.socket.addEventListener('open', () => {
            wsLogger.info('CONNECTION', 'WebSocket连接成功', null, { readyState: this.socket?.readyState })
            this.reconnectAttempts = 0 // 重置重连次数
            this.hasLoggedIn = false // 重置登录状态

            // 启动网络检测
            this.startNetworkCheck()

            this.sendLoginMessage()
        })

        // 错误处理
        this.socket.addEventListener('error', (error) => {
            wsLogger.error('CONNECTION', 'WebSocket连接错误', error, { readyState: this.socket?.readyState })
            ElMessage.error('WebSocket连接错误，请检查网络连接')
        })

        // 接收消息
        this.socket.addEventListener('message', (event) => {
            wsLogger.debug('MESSAGE', '收到WebSocket消息', { data: event.data, size: event.data.length })
            this.handleMessage(event)
        })

        // 连接关闭
        this.socket.addEventListener('close', (event) => {
            wsLogger.warn('CONNECTION', 'WebSocket连接关闭', null, {
                code: event.code,
                reason: event.reason,
                wasClean: event.wasClean,
                readyState: this.socket?.readyState
            })

            this.handleClose(event)
        })
    }

    /**
     * 发送登录消息
     */
    private async sendLoginMessage(): Promise<void> {
        if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
            console.log('❌ WebSocket未连接，无法发送登录消息')
            return
        }

        if (this.hasLoggedIn) {
            console.log('🔄 已登录，跳过重复登录')
            return
        }

        const userStore = useUserStore()
        const computerRealName = await getComputerName()

        const loginData: LoginMessage = {
            s: 'login',
            store_id: userStore.userInfo?.store_id || null,
            token: LocalStorage.get('token') || '',
            version: '2',
            computer_real_name: computerRealName
        }

        console.log('🔐 发送登录消息')
        this.socket.send(JSON.stringify(loginData))
    }

    /**
     * 处理接收到的消息
     * @param event 消息事件
     */
    private async handleMessage(event: MessageEvent): Promise<void> {
        try {
            const message: WebSocketMessage = JSON.parse(event.data)

            // 创建消息唯一标识符（基于消息内容和时间戳）
            const messageId = message.message_id

            // 检查是否已经处理过这条消息（心跳消息和登录消息不参与去重）
            if (this.processedMessages.has(messageId) && message.s !== 'heartbeat' && message.s !== 'login' && message.s !== 'message') {
                console.log('🔄 跳过重复消息:', message.s, messageId)
                return
            }

            // 记录已处理的消息（心跳消息不记录）
            if (message.s !== 'heartbeat') {
                this.processedMessages.add(messageId)
            }

            // 清理过期的消息记录（保留最近1000条）
            if (this.processedMessages.size > 1000) {
                const messagesArray = Array.from(this.processedMessages)
                this.processedMessages.clear()
                messagesArray.slice(-500).forEach(id => this.processedMessages.add(id))
            }

            switch (message.s) {
                case 'login':
                    this.handleLoginResponse(message)
                    break
                case 'desk_re': // 桌台变动消息
                    handleSystemMessage(message)
                    sendAckMessage(messageId)
                    break
                case 'message': // 挂账消息
                    
                    handleGuazhangMessage(message)
                    // sendAckMessage(messageId)
                    break
                case 'ticket_cxt':
                    if (message.status === 200 && message.data) {
                        // 异步处理厨信通消息，不阻塞心跳
                        handleCXTMessage(message.data).catch(error => {
                            wsLogger.error('ERROR', '厨信通消息处理失败', error)
                            console.error('厨信通消息处理失败:', error)
                        }).finally(() => {
                            sendAckMessage(messageId)
                        })
                    }
                    break
                case 'ticket':
                    const ticketId = message.data?.ticket_id || 'unknown'
                    if (message.status === 200 && message.data) {
                        // 异步处理打印消息，不阻塞心跳
                        handlePrintMessage(message.data).catch(error => {
                            wsLogger.error('ERROR', '打印消息处理失败', error)
                            console.error('打印消息处理失败:', error)
                        }).finally(() => {
                            sendAckMessage(messageId)
                        })
                    } else {
                        ElMessage.error('打印推送失败')
                    }
                    break
                case 'heartbeat':
                    this.handleHeartbeatResponse()
                    break
                default:
                    console.log('❓ 未知消息类型:', message.s)
            }
        } catch (error) {
            console.error('❌ WebSocket消息解析失败:', error)
        }
    }

    /**
     * 处理登录响应
     * @param message 登录响应消息
     */
    private handleLoginResponse(message: WebSocketMessage): void {
        console.log('🔐 处理登录响应:', message.status, message.message)
        if (message.status === 200) {
            console.log('✅ 登录成功，开始心跳')
            this.hasLoggedIn = true // 标记已登录
            this.startHeartbeat()

            // 单独启动订单状态报告，不阻塞心跳
            orderStateReport()
        } else {
            console.error('❌ 登录失败:', message.message)
            this.hasLoggedIn = false // 登录失败，重置状态
            ElMessage.error('WebSocket登录失败: ' + (message.message || '未知错误'))
        }
    }

    /**
     * 开始心跳检测
     */
    private startHeartbeat(): void {
        // 防止重复启动心跳
        if (this.isHeartbeatRunning) {
            wsLogger.debug('HEARTBEAT', '心跳已在运行，跳过重复启动')
            return
        }

        if (this.interval) {
            clearTimeout(this.interval) // 改为 clearTimeout
        }

        wsLogger.info('HEARTBEAT', `开始心跳检测，间隔: ${this.heartbeatInterval / 1000}秒`)
        this.heartbeatSendCount = 0 // 重置心跳计数
        this.isHeartbeatRunning = true // 标记心跳正在运行

        // 使用 setTimeout 递归替代 setInterval，避免浏览器节流
        this.scheduleNextHeartbeat()
    }

    /**
     * 调度下一次心跳
     */
    private scheduleNextHeartbeat(): void {
        wsLogger.debug('HEARTBEAT', `调度心跳定时器 - ${new Date().toLocaleTimeString()}`, null, { interval: this.heartbeatInterval })

        this.interval = setTimeout(() => {
            wsLogger.debug('HEARTBEAT', `心跳定时器触发 - ${new Date().toLocaleTimeString()}`)

            if (this.socket && this.socket.readyState === WebSocket.OPEN) {
                this.heartbeatSendCount++
                const heartbeatMessage: HeartbeatMessage = { s: 'heartbeat' }
                this.socket.send(JSON.stringify(heartbeatMessage))
                wsLogger.debug('HEARTBEAT', `发送心跳消息 (第${this.heartbeatSendCount}次) - ${new Date().toLocaleTimeString()}`)

                // 记录发送时间
                this.lastHeartbeatTime = Date.now()

                // 启动心跳超时检测
                this.startHeartbeatTimeout()

                // 调度下一次心跳
                this.scheduleNextHeartbeat()
            } else {
                wsLogger.warn('HEARTBEAT', 'WebSocket连接异常，停止心跳', null, { readyState: this.socket?.readyState })
                // 不要停止心跳，让重连机制处理
            }
        }, this.heartbeatInterval)
    }

    /**
     * 处理心跳响应
     */
    private handleHeartbeatResponse(): void {
        wsLogger.debug('HEARTBEAT', '收到心跳响应')
        this.lastHeartbeatTime = Date.now()

        // 清除超时定时器
        this.clearHeartbeatTimeout()
    }

    /**
     * 清除心跳超时定时器
     */
    private clearHeartbeatTimeout(): void {
        if (this.heartbeatTimeoutTimer) {
            clearTimeout(this.heartbeatTimeoutTimer)
            this.heartbeatTimeoutTimer = null
            console.log('✅ 清除心跳超时定时器')
        }
    }

    /**
     * 启动心跳超时检测
     */
    private startHeartbeatTimeout(): void {
        // 清除之前的超时定时器
        this.clearHeartbeatTimeout()

        wsLogger.debug('HEARTBEAT', `启动心跳超时检测 (${this.heartbeatTimeout / 1000}秒)`)
        this.heartbeatTimeoutTimer = setTimeout(() => {
            wsLogger.warn('HEARTBEAT', `心跳超时 (第${this.heartbeatSendCount}次心跳)，主动断开连接`)
            this.forceReconnect()
        }, this.heartbeatTimeout)
    }

    /**
     * 强制重连
     */
    private forceReconnect(): void {
        wsLogger.warn('RECONNECT', '强制重连')
        if (this.socket) {
            this.socket.close()
        }
        this.socket = null
        this.connect()
    }

    /**
     * 停止心跳检测
     */
    private stopHeartbeat(): void {
        wsLogger.info('HEARTBEAT', '停止心跳检测')
        this.isHeartbeatRunning = false // 标记心跳停止

        if (this.interval) {
            clearTimeout(this.interval) // 改为 clearTimeout
            this.interval = null
        }

        if (this.heartbeatTimeoutTimer) {
            clearTimeout(this.heartbeatTimeoutTimer)
            this.heartbeatTimeoutTimer = null
        }
    }

    /**
     * 处理连接关闭
     * @param event 关闭事件
     */
    private handleClose(event: CloseEvent): void {
        console.log('🔌 WebSocket连接关闭，代码:', event.code, '原因:', event.reason)

        // 关闭心跳的发送
        this.stopHeartbeat()

        // 如果是手动断开，不进行重连
        if (this.isManualDisconnect) {
            console.log('🔌 手动断开连接，不进行重连')
            return
        }

        // 清除重连定时器
        if (this.reconnectTimeout) {
            clearTimeout(this.reconnectTimeout)
        }

        // 计算重连延迟（指数退避）
        const delay = Math.min(
            this.baseReconnectDelay * Math.pow(2, this.reconnectAttempts),
            this.maxReconnectDelay
        )

        console.log(`🔄 ${delay / 1000}秒后进行第${this.reconnectAttempts + 1}次重连`)
        if (this.isOnline) {
            this.reconnectTimeout = setTimeout(() => {
                this.socket = null
                this.reconnectAttempts++
                this.connect()
            }, delay)
        } else {
            console.log("网络问题，不进行重连");
        }

    }

    /**
     * 断开连接
     */
    disconnect(): void {
        wsLogger.info('CONNECTION', '手动断开WebSocket连接')
        this.isManualDisconnect = true

        this.stopHeartbeat()
        this.stopNetworkCheck()

        if (this.reconnectTimeout) {
            clearTimeout(this.reconnectTimeout)
            this.reconnectTimeout = null
        }

        if (this.socket) {
            this.socket.close()
            this.socket = null
        }
    }

    /**
     * 获取连接状态
     */
    get isConnected(): boolean {
        return this.socket !== null && this.socket.readyState === WebSocket.OPEN
    }

    /**
     * 获取连接状态描述
     */
    get connectionState(): string {
        if (!this.socket) return 'DISCONNECTED'

        switch (this.socket.readyState) {
            case WebSocket.CONNECTING:
                return 'CONNECTING'
            case WebSocket.OPEN:
                return 'CONNECTED'
            case WebSocket.CLOSING:
                return 'CLOSING'
            case WebSocket.CLOSED:
                return 'CLOSED'
            default:
                return 'UNKNOWN'
        }
    }

    /**
     * 发送消息
     * @param message 要发送的消息
     */
    sendMessage(message: string): void {
        if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
            throw new Error('WebSocket未连接，无法发送消息')
        }
        this.socket.send(message)
    }
}

// 创建全局WebSocket管理器实例
export const webSocketManager = new WebSocketManager()

// 导出便捷函数
export function initWebSocket(): void {
    webSocketManager.connect()
}

export function disconnectWebSocket(): void {
    webSocketManager.disconnect()
}

export function getWebSocketStatus(): { isConnected: boolean; state: string } {
    return {
        isConnected: webSocketManager.isConnected,
        state: webSocketManager.connectionState
    }
}

export { sendAckMessage }

// 默认导出
export default webSocketManager